package server

import (
	"cache-go/interface/database"
	"cache-go/lib/sync/atomic"
	"cache-go/parser"
	"cache-go/protocol"
	"cache-go/redis/connection"
	"context"
	"fmt"
	"io"
	"net"
	"strings"
	"sync"

	database2 "cache-go/database"
)

var (
	unknowErrReplyBytes = []byte("-ERR unknown\r\n")
)

type Handler struct {
	activeConn sync.Map // server 要维护多个活跃连接
	db         database.DB
	closing    atomic.Boolean // 是否关闭
}

func (h *Handler) closeClient(client *connection.Connection) {
	client.Close()
	h.activeConn.Delete(client)
}

func (h *Handler) Handle(ctx context.Context, conn net.Conn) {
	if h.closing.Get() {
		_ = conn.Close()
		return
	}
	// 封装conn
	client := connection.NewConn(conn)
	h.activeConn.Store(client, struct{}{})
	// 解析命令
	ch := parser.ParseStream(conn)
	for payload := range ch {
		if payload.Err != nil {
			if payload.Err == io.EOF ||
				payload.Err == io.ErrUnexpectedEOF ||
				strings.Contains(payload.Err.Error(), "use of closed network connection") {
				h.closeClient(client)
				fmt.Println("connection closed: " + client.RemoteAddr())
				return
			}
		}

		if payload.Data == nil {
			fmt.Println("empty payload")
			continue
		}
		r, ok := payload.Data.(*protocol.MultiBulkReply)
		if !ok {
			fmt.Println("require multi bulk protocol")
			continue
		}
		result := h.db.Exec(client, r.Args)
		if result != nil {
			_, _ = client.Write(result.ToBytes())
		} else {
			_, _ = client.Write(unknowErrReplyBytes)
		}
	}

}

func (h *Handler) Close() error {
	h.closing.Set(true)
	h.activeConn.Range(func(key interface{}, val interface{}) bool {
		client := key.(*connection.Connection)
		_ = client.Close()
		return true
	})
	h.db.Close()
	return nil
}

func MakeHandler() *Handler {
	var db = database2.NewStandaloneServer()
	return &Handler{
		db: db,
	}

}
